//
// Created by 78472 on 2022/5/15.
//

#include "serviceRequestHandler.h"
#include "siteService/nlohmann/json.hpp"
#include "siteService/service_site_manager.h"
#include "qlibc/QData.h"
#include "../param.h"
#include "common/httpUtil.h"
#include "log/Logging.h"
#include "../sourceManage/deviceManager.h"
#include "../sourceManage/groupManager.h"
#include "../sourceManage/statusManager.h"
#include <vector>
#include <regex>

using namespace servicesite;

namespace synergy {

    std::vector<string> sceneVec = {
      "constantBrightnessModeStart",
      "constantBrightnessModeStop",
      "constantBrightnessModeFlag",

      "comfortableDinnerModeStart",
      "comfortableDinnerModeStop",

      "readModeStart",
      "readModeStop",

      "cookModeStart",
      "cookModeStop",

      "enterHouseholdModeStart",
      "enterHouseholdNoPersonModeStart",

      "viewingSceneStart",
      "viewingSceneStop"
    };

    static const nlohmann::json okResponse = {
            {"code",     0},
            {"error",    "ok"},
            {"response", {}}
    };

    static const nlohmann::json errResponse = {
            {"code",     1},
            {"error",    "failed"},
            {"response", {}}
    };


  

    void sendRequest(const Request& request, Response& response){
        qlibc::QData requestData(request.body), responseData;
        string sourceSite = requestData.getData("request").getString("sourceSite");
        requestData.asValue()["request"].removeMember("sourceSite");
        std::set<string> siteNames = SiteRecord::getInstance()->getSiteName();
        for(auto& siteName : siteNames){
            if(siteName == sourceSite){
                LOG_GREEN << "requestData: " << requestData.toJsonString();
                SiteRecord::getInstance()->sendRequest2Site(siteName, requestData, responseData);
                LOG_BLUE << "responseData: " << responseData.toJsonString();
                if(responseData.empty()){
                    qlibc::QData ret;
                    ret.setInt("code", -1);
                    ret.setString("msg", "response is empty");
                    ret.putData("response", qlibc::QData());
                    response.set_content(ret.toJsonString(), "text/json");
                }else{
                    response.set_content(responseData.toJsonString(), "text/json");
                }
                return;
            }
        }

        //没有找到对应的站点
        qlibc::QData ret;
        ret.setInt("code", -1);
        ret.setString("msg", "need sourceSite to deliever!!!");
        ret.putData("response", qlibc::QData());
        response.set_content(ret.toJsonString(), "text/json");
    }


//设备控制
    int deviceControl_service_handler(const Request& request, Response& response){
        LOG_INFO << "synergy->deviceControl_service_handler: " << qlibc::QData(request.body).toJsonString();
        std::map<string, qlibc::QData> controlDeviceListMap;
        qlibc::QData controlDeviceList = qlibc::QData(request.body).getData("request").getData("device_list");
        Json::ArrayIndex size = controlDeviceList.size();
        for(Json::ArrayIndex i = 0; i < size; ++i){
            qlibc::QData item = controlDeviceList.getArrayElement(i);
            string device_id = item.getString("device_id");
            string inSourceSite = item.getString("sourceSite");
            string outSourceSite;
            if(DeviceManager::getInstance()->isInDeviceList(device_id, inSourceSite, outSourceSite)){    //待控制设备存在于设备列表中
                //按设备来源归类设备
                auto pos = controlDeviceListMap.find(outSourceSite);
                if(pos != controlDeviceListMap.end()){
                    pos->second.append(DeviceManager::getInstance()->restoreMac(item, inSourceSite));
                }else{
                    controlDeviceListMap.insert(
                            std::make_pair(outSourceSite,qlibc::QData().append(DeviceManager::getInstance()->restoreMac(item, inSourceSite))));
                }
            }
        }

        //发送控制命令到相应的站点
        for(auto& elem : controlDeviceListMap){    //按设备来源发送命令
            qlibc::QData controlRequest, controlResponse;
            controlRequest.setString("service_id", "control_device");
            controlRequest.putData("request", qlibc::QData().putData("device_list", elem.second));
            LOG_GREEN << elem.first << " controlRequest: " << controlRequest.toJsonString();
            SiteRecord::getInstance()->sendRequest2Site(elem.first, controlRequest, controlResponse);
            LOG_BLUE << elem.first << " controlResponse: " << controlResponse.toJsonString();
        }

        response.set_content(okResponse.dump(), "text/json");
        return 0;
    }

    int deviceControl_query_service_handler(const Request & request, Response & response)
    {
        LOG_INFO << "synergy->deviceControl_query_service_handler: " << qlibc::QData(request.body).toJsonString();
        sendRequest(request, response);
        return 0;
    }

//获取设备列表
    int getDeviceList_service_handler(const Request &request, Response &response) {
        LOG_INFO << "synergy->getDeviceList_service_handler";
        qlibc::QData res;
        res.putData("device_list", DeviceManager::getInstance()->getAllDeviceList());

        qlibc::QData data;
        data.setInt("code", 0);
        data.setString("error", "ok");
        data.putData("response", res);

        response.set_content(data.toJsonString(), "text/json");
        return 0;
    }

//获取设备状态
    int get_device_state_service_handler(const Request& request, Response& response){
        LOG_INFO << "synergy->get_device_state_service_handler: " << qlibc::QData(request.body).toJsonString();
        sendRequest(request, response);
        return 0;
    }

    int get_device_state_all_service_handler(const Request &request, Response &response)
    {
        qlibc::QData requestData(request.body);
        LOG_INFO << "synergy->get_device_state_all_service_handler: " << requestData.toJsonString();
    
        qlibc::QData statusDataList = StatusManager::getInstance()->getStatusDdata().getData("device_list");
        qlibc::QData data;
        data.setInt("code", 0);
        data.setString("error", "ok");
        data.putData("response", qlibc::QData().putData("device_list", statusDataList));
        response.set_content(data.toJsonString(), "text/json");
        return 0;
    }



//分组控制
    int groupControl_service_handler(const Request& request, Response& response){
        LOG_INFO << "synergy->groupControl_service_handler: " << qlibc::QData(request.body).toJsonString();
        //判断设备属于哪个站点
        std::map<string, qlibc::QData> controlGroupListMap;
        qlibc::QData controlGroupList = qlibc::QData(request.body).getData("request").getData("group_list");
        Json::ArrayIndex size = controlGroupList.size();
        for(Json::ArrayIndex i = 0; i < size; ++i){
            qlibc::QData item = controlGroupList.getArrayElement(i);
            string group_id = item.getString("group_id");
            string inSourceSite = item.getString("sourceSite");
            string outSourceSite;
            if(GroupManager::getInstance()->isInGroupList(group_id, inSourceSite,outSourceSite)){
                auto pos = controlGroupListMap.find(outSourceSite);
                if(pos != controlGroupListMap.end()){
                    pos->second.append(GroupManager::getInstance()->restoreGrp(item, inSourceSite));
                }else{
                    controlGroupListMap.insert(std::make_pair(outSourceSite,
                                                              qlibc::QData().append(GroupManager::getInstance()->restoreGrp(item, inSourceSite))));
                }
            }
        }

        //发送控制命令到相应的站点
        for(auto& elem : controlGroupListMap){
            qlibc::QData controlRequest, controlResponse;
            controlRequest.setString("service_id", "control_group");
            controlRequest.putData("request", qlibc::QData().putData("group_list", elem.second));
            LOG_GREEN << elem.first << " controlRequest: " << controlRequest.toJsonString();
            SiteRecord::getInstance()->sendRequest2Site(elem.first, controlRequest, controlResponse);
            LOG_BLUE << elem.first << " controlResponse: " << controlResponse.toJsonString();
        }

        //如果group_id含有FFFF
        for(Json::ArrayIndex i = 0; i < size; ++i){
            qlibc::QData item = controlGroupList.getArrayElement(i);
            string group_id = item.getString("group_id");
            string sourceSite = item.getString("sourceSite");
            string group_uid = group_id;
            if(!sourceSite.empty()){
                group_uid.append(">").append(sourceSite);
            }

            smatch sm;
            if(regex_match(group_uid, sm,regex("FFFF>(.*)"))){
                item.setString("group_id", "FFFF");
                item.removeMember("sourceSite");
                string siteName = sm.str(1);

                qlibc::QData controlRequest, controlResponse;
                qlibc::QData groupList;
                groupList.append(item);
                controlRequest.setString("service_id", "control_group");
                controlRequest.putData("request", qlibc::QData().putData("group_list", groupList));
                LOG_GREEN << siteName << " controlRequest: " << controlRequest.toJsonString();
                SiteRecord::getInstance()->sendRequest2Site(siteName, controlRequest, controlResponse);
                LOG_BLUE << siteName << " controlResponse: " << controlResponse.toJsonString();
            }
        }

        response.set_content(okResponse.dump(), "text/json");
        return 0;
    }



//获取分组列表
    int getGroupList_service_handler(const Request &request, Response &response) {
        LOG_INFO << "synergy->getGroupList_service_handler: " << qlibc::QData(request.body).toJsonString();
        LOG_INFO << "getGroupList_service_handler";
        qlibc::QData res;
        res.putData("group_list", GroupManager::getInstance()->getAllGroupList());

        qlibc::QData data;
        data.setInt("code", 0);
        data.setString("error", "ok");
        data.putData("response", res);

        response.set_content(data.toJsonString(), "text/json");
        return 0;
    }

//更新设备列表
    int updateDeviceList_service_handler(const Request& request, Response& response){
        LOG_INFO << "synergy->updateDeviceList_service_handler...";
        DeviceManager::getInstance()->updateDeviceList();
        qlibc::QData ret;
        ret.setInt("code", 0);
        ret.setString("msg", "success");
        response.set_content(ret.toJsonString(), "text/json");
        return 0;
    }

//更新组列表
    int updateGroupList_service_handler(const Request& request, Response& response){
        LOG_INFO << "synergy->updateGroupList_service_handler...";
        GroupManager::getInstance()->updateGroupList();
        qlibc::QData ret;
        ret.setInt("code", 0);
        ret.setString("msg", "success");
        response.set_content(ret.toJsonString(), "text/json");
        return 0;
    }



    int messagePublish_service_request_handler(const Request &request, Response &response)
    {
        qlibc::QData requestData(request.body);
        LOG_INFO << "synergy->messagePublish_service_request_handler: " << requestData.toJsonString();
        string message_id = requestData.getData("request").getString("message_id");
        ServiceSiteManager::getInstance()->publishMessage(message_id, requestData.getData("request").toJsonString(), false, 1);
        
        qlibc::QData ret;
        ret.setInt("code", 0);
        ret.setString("error", "ok");
        ret.putData("response", qlibc::QData());
        response.set_content(ret.toJsonString(), "text/json");
        return 0;
    }


    void messagePublish(const Request& request){
        qlibc::QData requestData(request.body);
        LOG_INFO << "synergy->messagePublish: " << qlibc::QData(request.body).toJsonString();
        string message_id = requestData.getString("message_id");
        ServiceSiteManager::getInstance()->publishMessage(message_id, requestData.toJsonString(), false, 1);

        std::set<string> msgSet{
            DeviceOnOffLineMsg,
            DeviceListChanged,
            SingleDeviceBindSuccessMsg,
            SingleDeviceUnbindSuccessMsg,
            Key_bind_success_messageID
        };
        
        if(msgSet.find(message_id) != msgSet.end()){
            siteManager::getInstance()->trigger_updateSite();
        }
        return;
    }


    void trigger_devGrp_update_messageHandle(const Request &request)
    {
        qlibc::QData requestBody(request.body);
        LOG_INFO << "trigger_devGrp_update_messageHandle: " << requestBody.toJsonString();
        std::set<string> deviceSiteSet{BleSiteID, TvAdapterSiteID, ZigbeeSiteID, BtDeviceSiteID, Site_irc_SiteID};
        string site_id = requestBody.getData("content").getString("site_id");
        if(deviceSiteSet.find(site_id) != deviceSiteSet.end()){
            siteManager::getInstance()->trigger_updateSite();
        }        
    }


    void trigger_dgp_update_meesageHandle(const Request& request){
        qlibc::QData requestBody(request.body);
        LOG_INFO << "trigger_dgp_update_meesageHandle: " << requestBody.toJsonString();
        siteManager::getInstance()->trigger_updateSite();
        siteManager::getInstance()->trigger_updatePanelList();
    }


    void uploadLogHandler(const Request &request)
    {
        qlibc::QData requestBody(request.body);
        LOG_INFO << "uploadLogHandler: " << requestBody.toJsonString();
        string mac = requestBody.getData("content").getString("mac");
        qlibc::QData siteRequest, siteResponse;
        siteRequest.setString("service_id", "get_self_info");
        siteRequest.putData("request", qlibc::QData());
        LOG_GREEN << "get_self_info request: " << siteRequest.toJsonString();
        if(httpUtil::sitePostRequest("127.0.0.1", 9006, siteRequest, siteResponse)){
            LOG_BLUE << "get_self_info response: " << siteResponse.toJsonString();
            string deivce_mac = siteResponse.getData("response").getString("device_mac");
            uploadLog::getInstance()->upLoad(mac, "synergySiteLog.txt", "/data/changhong/edge_midware/lhy/synergySiteLog.txt");  
        }
    }
}


